package ${commonPackageName}.utils;

import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ${commonPackageName}.enums.ExceptionEnum;
import ${commonPackageName}.strategy.RedissonLocker;
/**
 * redisson(redis分布式锁)
 * @author lizihao
 *
 */
@Component
public class RedisLockUtil implements RedissonLocker{

	@Autowired
    private RedissonClient redissonClient;
	
	/**
	 * 根据key上锁,没时间限制(这里没有获取到锁的话线程一直block的)
	 * @param lockKey 锁名称
	 * @throws Exception 
	 */
	@Override
	public RLock lock(String lockKey) throws Exception{
		RLock lock = null;
		try {
			lock = redissonClient.getLock(lockKey);
			lock.lock();
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
        return lock;
	}
	
	/**
	 * 根据key上锁,指定锁失效时间(这里没有获取到锁的话线程一直block的)
	 * @param lockKey 锁名称
	 * @param timeout 上锁后释放锁时间(默认单位秒)
	 * @throws Exception 
	 */
	@Override
	public RLock lock(String lockKey, int timeout) throws Exception {
		RLock lock = null;
		try {
			lock = redissonClient.getLock(lockKey);
	        lock.lock(timeout, TimeUnit.SECONDS);
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
        return lock;
	}
	
	/**
	 * 根据key上锁,指定失效时间和时间单位(这里没有获取到锁的话线程一直block的)
	 * @param lockKey 锁名称
	 * @param unit 时间单位
	 * @param timeout 上锁后释放锁时间(默认单位秒)
	 * @throws Exception 
	 */
	@Override
	public RLock lock(String lockKey, TimeUnit unit, int timeout) throws Exception {
		RLock lock = null;
		try {
			lock = redissonClient.getLock(lockKey);
			lock.lock(timeout, unit);
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
        return lock;
	}
	
	/**
	 * 尝试等待锁
	 * @param lockKey 锁名称
	 * @param unit 时间单位
	 * @param waitTime 等待锁时间
	 * @param leaseTime 上锁后释放锁时间
	 */
	@Override
	public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
		RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
	}

	/**
	 * 解锁(须同一个线程内解锁)
	 * @param 锁名称
	 * @throws Exception 
	 */
	@Override
	public void unlock(String lockKey) throws Exception {
		try {
			RLock lock = redissonClient.getLock(lockKey);
	        lock.unlock();
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
	}
	
	/**
	 * 解锁(同一个线程内解锁)
	 * @param lock 锁对象
	 * @throws Exception 
	 */
	@Override
	public void unlock(RLock lock) throws Exception {
		try {
			lock.unlock();
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
	}
	/**
	 * 解锁(不需要同一个线程内解锁)
	 * @param 锁名称
	 * @throws Exception 
	 */
	@Override
	public void forceUnlock(String lockKey) throws Exception {
		try {
			RLock lock = redissonClient.getLock(lockKey);
	        lock.forceUnlock();
		} catch (Exception e) {
			throw new Exception(ExceptionEnum.REDISSON_ERROR.getMsg());
		}
	}
}
